﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Luna;
using System.Xml;
using System.Diagnostics;

namespace TextDataExtractor.DEML {
	
	public class Section : CompositePattern {
		private ITextLocator startLocator;
		private ITextLocator endLocator;
		private IList<string> startLocatorOption, endLocatorOption;

		public ITextLocator StartLocator {
			get {
				return this.startLocator;
			}
			set {
				this.startLocator = value;
			}
		}

		public ITextLocator EndLocator {
			get {
				return this.endLocator;
			}
			set {
				this.endLocator = value;
			}
		}

		protected override void processChildNode(System.Xml.XmlNode child, DemlRegistry registry) {
			if (child.Name.Equals("begin") || child.Name.Equals("end")) {
				ITextLocator locator = null;
				foreach (XmlNode node in child.ChildNodes)
					if (DemlFactory.Instance.isElementType(ElementType.TextLocator, node.Name)) {
						locator = (ITextLocator)DemlFactory.Instance.createElement(ElementType.TextLocator, node.Name);
						locator.loadFromXml(node, registry);
						break;
					}

				if (child.Name.Equals("begin")) {
					startLocatorOption = child.getAttribute("option", String.Empty).splitEx(',');
					startLocator = locator;
				}
				else {
					endLocatorOption = child.getAttribute("option", string.Empty).splitEx(',');
					endLocator = locator;
				}	
			}
			else
				base.processChildNode(child, registry);
		}

		public override int match(System.IO.StreamReader input, ref string buffer) {
			int result = 0;
			int bufsize = 10 * 1024;
			while (result == 0) {
				//if (buffer.Length >= bufsize * 10)
					//Debugger.Break();
				result = match(buffer);
				if (Skipped || result > 0)
					buffer = buffer.Substring(EndIndex + 1);
				else if (!input.EndOfStream) {
					char[] charbuf = new char[bufsize];
					int len = input.Read(charbuf, 0, bufsize);
					int idxToCopy = StartIndex >= 0 && StartIndex < buffer.Length ? StartIndex : Math.Max(0, buffer.Length - 500);
					
					if (idxToCopy < 0)
						buffer =  new string(charbuf, 0, len);
					else
						buffer = buffer.Substring(idxToCopy) + new string(charbuf, 0, len);
				}
				else break;
			}
			return result;
		}

		public override int match(string input) {
			Skipped = false;
			StartIndex = StartLocator != null ? StartLocator.locate(0, input) : 0;
			int startLen = StartLocator != null ? StartLocator.Length : 0;

			int endIndex = EndIndex = EndLocator != null ? EndLocator.locate(StartIndex + 1, input) : StartIndex + startLen;
			int endLen = EndLocator != null ? EndLocator.Length : 0;
			int result = 0;
			if (StartIndex >= 0 && StartIndex < input.Length && EndIndex >= 0 && EndIndex < input.Length) {
				int sidx = startLocatorOption != null && startLocatorOption.Contains("inclusive") ? StartIndex : StartIndex + startLen;
				int eidx = endLocatorOption != null && endLocatorOption.Contains("inclusive") ? EndIndex + endLen - 1: EndIndex - 1;
				MatchedText = input.Substring(sidx, eidx - sidx + 1);

				Skipped = Registry.fireEvent<bool>(new DemlEventArg(DemlEvent.BeginMatch, this, null), false);

				if (!Skipped) 
					result = base.match(MatchedText);

				EndIndex = eidx;
			}
			return result;
		}

		public override void CopyTo(DemlElement target) {
			base.CopyTo(target);
			Section p = (Section)target;
			p.startLocator = startLocator != null ? (ITextLocator)startLocator.Clone() : null;
			p.endLocator = endLocator != null ? (ITextLocator)endLocator.Clone() : null;
		}

		protected void test() {
			string s = System.IO.File.ReadAllText("mfsa.html");
			FindTextLocator sl, el;

			StartLocator = sl = new FindTextLocator() { FindOperation =  FindTextLocatorOperation.Equal, Value = "title" };
			EndLocator = el = new FindTextLocator() { FindOperation = FindTextLocatorOperation.Equal, Value = "/title" };
			match(s);

			startLocatorOption = "inclusive".splitEx(',');
			match(s);

			endLocatorOption = "inclusive".splitEx(',');
			match(s);

			EndLocator = null;
			match(s);

			//endLocatorOption.Clear();
			sl.Value = "<div id=\"footer";
			el.FindOperation = FindTextLocatorOperation.CloseTag;
			el.Value = "div";
			EndLocator = el;
			match(s);
		}
	}
}
